<!-- DynamicForm.vue -->
<template>
  <el-form
    ref="formRef"
    :model="formData"
    :rules="formRules"
    :label-width="labelWidth || '100px'"
    :label-position="labelPosition"
    class="dynamic-form"
  >
    <el-row :gutter="gutter" class="form-area">
      <template v-for="(item, index) in formConfig" :key="item.prop || index">
        <!-- 动态列布局 -->
        <el-col
          v-if="checkShowCondition(item)"
          :span="item.span || 24"
          :xs="item.xs || 24"
          :sm="item.sm || item.span || 12"
          :md="item.md || item.span || 8"
          :lg="item.lg || item.span || 6"
          :xl="item.xl || item.span || 4"
        >
          <el-form-item :label="item.label" :prop="item.prop" :required="item.required">
            <!-- 多层组件渲染 -->
            <template v-if="isGroupComponent(item.type)">
              <component
                :is="getComponentType(item.type)"
                v-model="formData[item.prop]"
                v-bind="item.attrs"
                :placeholder="item.placeholder || `请选择${item.label}`"
                :disabled="item.disabled || checkDisableCondition(item)"
              >
                <!-- 动态渲染子组件 -->
                <template v-if="item.children">
                  <component
                    v-for="(child, cIndex) in item.children"
                    :key="cIndex"
                    :is="getChildComponentType(item.type, child.type)"
                    :label="child.label"
                    :value="child.value"
                    :disabled="child.disabled"
                    :border="item.type === 'checkbox-group' ? false : undefined"
                  />
                </template>
              </component>
            </template>
            <!-- 普通组件渲染 -->
            <component
              v-else
              :is="getComponentType(item.type)"
              v-model="formData[item.prop]"
              v-bind="item.attrs"
              :placeholder="item.placeholder || `请输入${item.label}`"
              :disabled="item.disabled || checkDisableCondition(item)"
              clearable
            />
          </el-form-item>
        </el-col>
        <!-- 自定义插槽 -->
        <template v-if="item.slot">
          <slot :name="item.slot" :form-data="formData" />
        </template>
      </template>
    </el-row>

    <!-- 提交按钮区域 -->
    <el-row v-if="showSubmitArea" :gutter="gutter" class="submit-area">
      <el-col :span="24">
        <el-form-item>
          <el-button type="primary" :loading="submitLoading" @click="handleSubmit">
            {{ submitText }}
          </el-button>
          <el-button v-if="showResetButton" @click="handleReset" :disabled="submitLoading">
            {{ resetText }}
          </el-button>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>

<script setup lang="ts">
  import type { FormInstance, FormRules } from 'element-plus'
  import { ElCheckbox, ElMessage, ElOption } from 'element-plus'
  import type { FormItemConfig } from './type'
  import DicSelect from '../Dictionary/DicSelect.vue'
  import DicRadio from '../Dictionary/DicRadio.vue'
  import CustomUpload from '../CustomUpload/index.vue'
  import { MdEditor } from 'md-editor-v3'
  // 导入IconSelector组件
  import IconSelector from '../IconSelector/IconSelector.vue'
  import ProTree from '../ProTree/index.vue'

  // 组件类型映射（支持嵌套结构）
  const componentMap = {
    input: ElInput,
    select: ElSelect,
    'tree-select': ElTreeSelect,
    'checkbox-group': ElCheckboxGroup,
    'radio-group': ElRadioGroup,
    date: ElDatePicker,
    switch: ElSwitch,
    textarea: ElInput,
    checkbox: ElCheckbox,
    radio: ElRadio,
    option: ElOption,
    'dict-select': DicSelect,
    'dict-radio': DicRadio,
    'md-editor': MdEditor,
    upload: CustomUpload,
    // 添加图标选择器映射
    'icon-selector': IconSelector,
    icon: IconSelector,
    tree: ProTree
  }

  const props = defineProps({
    formConfig: {
      type: Array as () => FormItemConfig[],
      required: true
    },
    modelValue: {
      type: Object,
      default: () => ({})
    },
    labelWidth: {
      type: [String, Number],
      default: '120px'
    },
    labelPosition: {
      type: String,
      default: 'right'
    },
    gutter: {
      type: Number,
      default: 20
    },
    showSubmitButton: {
      type: Boolean,
      default: false
    },
    showResetButton: {
      type: Boolean,
      default: true
    },
    submitText: {
      type: String,
      default: '提交'
    },
    resetText: {
      type: String,
      default: '重置'
    },
    submitLoading: {
      type: Boolean,
      default: false
    }
  })
  const checkDisableCondition = (item: FormItemConfig) => {
    if (!item.disableWhen) return false
    if (typeof item.disableWhen === 'function') {
      return item.disableWhen(formData.value)
    }
    return item.disableWhen
  }
  const checkShowCondition = (item: FormItemConfig) => {
    if (!item.showCondition) return true
    if (typeof item.showCondition === 'function') {
      return item.showCondition(formData.value)
    } else if (typeof item.showCondition === 'string') {
      return eval(item.showCondition)
    } else {
      return true
    }
  }

  const emit = defineEmits(['update:modelValue', 'validate', 'submit-success', 'submit-fail'])

  const formRef = ref<FormInstance>()
  const formData = ref<Record<string, any>>({})
  const formRules = computed<FormRules>(() => {
    const rules: FormRules = {}
    props.formConfig.forEach((item: FormItemConfig) => {
      if (item.rules) {
        // 遍历规则数组，如果存在 validator，则包装它以传入 formData
        const processedRules = item.rules.map(rule => {
          if (rule.validator) {
            const originalValidator = rule.validator
            return {
              ...rule,
              validator: (r: any, v: any, callback: any) =>
                originalValidator(r, v, callback, formData.value)
            }
          }
          return rule
        })
        rules[item.prop] = processedRules
      }
    })
    return rules
  })

  // 初始化表单数据
  watch(
    () => props.modelValue,
    (newVal: Record<string, any>) => {
      formData.value = { ...newVal }
    },
    { immediate: true, deep: true }
  )

  // 获取组件类型
  const getComponentType = (type: keyof typeof componentMap) => {
    return componentMap[type] || ElInput
  }

  // 获取子组件类型（针对group组件）
  const getChildComponentType = (
    parentType: keyof typeof componentMap,
    childType?: keyof typeof componentMap
  ) => {
    if (parentType === 'select') return ElOption
    if (parentType === 'checkbox-group') return ElCheckbox
    if (parentType === 'radio-group') return ElRadio
    return childType ? getComponentType(childType) : ElOption
  }

  // 判断是否为组容器组件
  const isGroupComponent = (type: keyof typeof componentMap) => {
    return ['select', 'checkbox-group', 'radio-group'].includes(type)
  }

  // 表单验证
  const validate = async () => {
    try {
      await formRef.value?.validate()
      emit('validate', true)
      return true
    } catch (error) {
      emit('validate', false)
      return false
    }
  }

  // 提交处理
  const handleSubmit = async () => {
    try {
      const isValid = await validate()
      if (!isValid) return
      emit('submit-success', formData.value)
    } catch (error) {
      emit('submit-fail', error)
      ElMessage.error('表单验证失败，请检查输入')
    }
  }

  // 重置处理
  const handleReset = () => {
    formRef.value?.resetFields()
    emit('update:modelValue', {})
    ElMessage.info('表单已重置')
  }

  // 暴露方法
  defineExpose({
    validate,
    handleSubmit,
    resetFields: handleReset,
    scrollToField: (prop: string, behavior: ScrollBehavior = 'smooth') => {
      nextTick(() => {
        const el = document.querySelector(`.el-form-item__label[for="${prop}"]`)
        if (el) {
          el.scrollIntoView({ behavior })
        }
      })
    }
  })

  // 计算属性：是否显示提交区域
  const showSubmitArea = computed(() => {
    // return props.showSubmitButton && !props.formConfig.some((item: FormItemConfig) => item.slot)
    return props.showSubmitButton
  })
</script>

<style scoped lang="scss">
  .dynamic-form {
    position: relative;
    width: 100%;
    padding: 20px 0;
    max-height: 100%;
    /*  */
    .form-area {
      &:has(+ .submit-area) {
        height: calc(100% - 75px);
        overflow-y: auto;
      }
    }
  }

  .submit-area {
    position: absolute;
    z-index: 1;
    width: 100%;
    bottom: 0;
    margin-top: 24px;
    border-top: 1px solid #ebeef5;
    padding-top: 24px;
  }

  .submit-area :deep(.el-form-item__content) {
    justify-content: flex-end;
  }
</style>
